using System;
using System.Collections.Generic;
using System.Reflection;

namespace System.Web.Core
{
    public class EntityRequest : BaseRequest
    {
        #region Private Members

        private int entityId = 0;
        private Entity entity = null;
        private string commandIdent = null;
        private bool returnAllField = true;
        private bool saveModifiedProperties = false;

        #endregion

        #region Public Properties

        public int EntityId
        {
            get
            {
                return entityId;
            }
            set
            {
                entityId = value;
            }
        }
        public Entity Entity
        {
            get
            {
                return entity;
            }
            set
            {
                entity = value;
            }
        }
        public string CommandIdent
        {
            get
            {
                return commandIdent;
            }
            set
            {
                commandIdent = value;
            }
        }
        public bool ReturnAllField
        {
            get
            {
                return returnAllField;
            }
            set
            {
                returnAllField = value;
            }
        }
        public bool SaveModifiedProperties
        {
            get
            {
                return saveModifiedProperties;
            }
            set
            {
                saveModifiedProperties = value;
            }
        }

        #endregion

        #region Public Methods

        public override BaseReply Send(BaseRequestBinder requestBinder)
        {
            BaseReply reply = requestBinder.Reply;
            SqlResult result;

            switch (Operation)
            {
                case OperationType.Get:
                    reply.Reply = EntityManager.GetEntity(requestBinder);
                    break;
                case OperationType.Add:
                    result = EntityManager.CreateEntity(requestBinder);
                    reply.Status = result.Status;
                    reply.Log = result.Message;
                    break;
                case OperationType.Update:
                    result = EntityManager.UpdateEntity(requestBinder);
                    reply.Status = result.Status;
                    reply.Log = result.Message;
                    break;
                case OperationType.Delete:
                    result = EntityManager.DeleteEntity(requestBinder);
                    reply.Status = result.Status;
                    reply.Log = result.Message;
                    break;
            }

            return reply;
        }
        protected override List<string> GetDefaultReturnFields()
        {
            if (Entity != null)
            {
                List<string> fieldNameList = new List<string>();
                foreach (PropertyInfo propertyInfo in Entity.GetType().GetProperties())
                {
                    if (typeof(Property).IsAssignableFrom(propertyInfo.PropertyType) && ((Property)propertyInfo.GetValue(Entity, null)).IsDBProperty)
                    {
                        fieldNameList.Add(Entity.GetDBFieldName(propertyInfo.Name));
                    }
                }
                return fieldNameList;
            }
            return null;
        }
        public override string GetReturnFieldString()
        {
            if (ReturnFields == null || ReturnFields.Count == 0)
            {
                ReturnFields = GetDefaultReturnFields();
            }
            List<string> formattedFields = new List<string>();
            foreach (string field in ReturnFields)
            {
                formattedFields.Add(field);
            }
            return string.Join(",", formattedFields.ToArray());
        }
        public string GetDBFieldName(string propertyName)
        {
            return Configuration.Instance.GetDBFieldName(this.Entity.GetType(), propertyName);
        }
        public string GetTableName()
        {
            return Configuration.Instance.GetTableName(this.Entity.GetType());
        }
        public static string GetDBFieldName(Type entityType, string propertyName)
        {
            return Configuration.Instance.GetDBFieldName(entityType, propertyName);
        }
        protected static string GetTableName(Type entityType)
        {
            return Configuration.Instance.GetTableName(entityType);
        }
        public void AddReturnProperty(string propertyName)
        {
            if (string.IsNullOrEmpty(propertyName))
            {
                return;
            }
            string fieldName = GetDBFieldName(Entity.GetType(), propertyName);
            if (!string.IsNullOrEmpty(fieldName))
            {
                if (!ReturnFields.Contains(fieldName))
                {
                    ReturnFields.Add(fieldName);
                }
            }
        }
        public void AddRangeReturnProperties(IEnumerable<string> propertyNames)
        {
            if (propertyNames == null)
            {
                return;
            }
            foreach (string propertyName in propertyNames)
            {
                AddReturnProperty(propertyName);
            }
        }
        public void RemoveReturnProperty(string propertyName)
        {
            if (string.IsNullOrEmpty(propertyName))
            {
                return;
            }
            string fieldName = GetDBFieldName(Entity.GetType(), propertyName);
            if (!string.IsNullOrEmpty(fieldName))
            {
                if (ReturnFields.Contains(fieldName))
                {
                    ReturnFields.Remove(fieldName);
                }
            }
        }
        public void RemoveAllReturnProperties()
        {
            ReturnFields.Clear();
        }

        #endregion
    }
    public class TEntityRequest<TEntity> : EntityRequest where TEntity : Entity, new()
    {
        public TEntityRequest()
        {
            Entity = new TEntity();
            ReturnFields = GetDefaultReturnFields();
        }
    }
}